import math
import re

from django.contrib.auth.hashers import check_password
from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import *

from django.utils.deprecation import MiddlewareMixin

from django.http import QueryDict

# 类视图调用
from django.utils.decorators import method_decorator

# 事务操作
from django.db import transaction


# 文件上传
class UpLoader(View):
    def post(self, request):
        # 接受文件
        file = request.FILES.get('file')
        # 写文件
        with open(os.path.join(UPLOAD_ROOT, '', file.name), 'wb')as f:
            for chunk in file.chunks():
                f.write(chunk)
        return HttpResponse(json.dumps({'filename': file.name}, ensure_ascii=False), content_type='applications/json')


# 定义验证码类
class MyCode(View):
    # 内置类方法
    def get_random_color(self):
        # 随机颜色
        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)
        # 返回元组,只有一个元素时要加一个‘，’r
        return (R, G, B)

    def get(self, request):
        # 定义画布
        image_size = (120, 50)
        # 定义图像对象
        image = Image.new('RGB', image_size, 'white')
        # 定义画笔
        draw = ImageDraw.Draw(image, 'RGB')
        # 定义字符串
        source = '123456789qwertyuiopasdfghjklzxcvbnm'
        # 定义容器
        code_str = ''
        # 每生成一位，取四次
        for i in range(4):
            # 获取字符颜色
            text_color = self.get_random_color()
            # 获取随机字符
            tmp_num = random.randrange(len(source))
            random_str = source[tmp_num]
            code_str += random_str
            draw.text((10 + 30 * i, 20), random_str, text_color)
        buf = io.BytesIO()
        image.save(buf, 'png')
        # 保存验证码
        request.session['code'] = code_str
        return HttpResponse(buf.getvalue(), 'image/png')


# md5加密
def make_password(my_passwrord):
    # 生成对象
    md5 = hashlib.md5()
    # 定义加密对象
    sign_str = my_passwrord
    # 转码
    sign_utf8 = str(sign_str).encode(encoding='utf8')
    # 加密
    md5.update(sign_utf8)
    # 生成密文
    md5_server = md5.hexdigest()
    return md5_server


# 注册
class RegisterView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        gender = request.data.get('gender')
        phone = request.data.get('phone')
        email = request.data.get('email')
        print(username, password, phone, gender)
        new_password = make_password(password)
        try:
            user = User(username=username, password=new_password, phone=phone, gender=gender, email=email)
            user.save()
            return Response({'code': 200, 'msg': '注册成功'})
        except Exception as e:
            print(e)
            return Response({'code': 405, 'msg': '注册失败'})


import jwt
import datetime


# 登录
class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username', None)
        password = request.data.get('password', None)
        active = request.data.get('active', None)
        new_code = request.data.get('code', None)
        active = int(active)
        code = request.session.get('code')
        print(code)
        # 获取用户信息
        user = User.objects.filter(Q(username=username) | Q(email=username) | Q(phone=username)).first()
        # 设置荷载信息
        play_load = {'exp': int((datetime.datetime.now() + datetime.timedelta(seconds=10000)).timestamp()),
                     'data': {'username': username, 'uid': user.id}}
        # 编码 前面有 b 的一串编码 bytes
        encode_jwt = jwt.encode(play_load, '123', algorithm='HS256')
        # 强转成字符串
        encode_str = str(encode_jwt, 'utf-8')
        # if code == new_code:
        if active == 0:
            user = User.objects.filter(username=username).first()
            if user:
                if make_password(password) == user.password:
                    return Response({'code': 200, 'msg': '登陆成功', 'jwt': encode_str})
                else:
                    return Response({'code': 400, 'msg': '密码不正确'})
            else:
                return Response({'code': 400, 'msg': '不存在该用户'})
        elif active == 1:
            user = User.objects.filter(phone=username).first()
            if user:
                if make_password(password) == user.password:
                    return Response({'code': 200, 'msg': '登陆成功', 'jwt': encode_str, })
                else:
                    return Response({'code': 400, 'msg': '密码不正确'})
            else:
                return Response({'code': 400, 'msg': '不存在该手机号'})
        else:
            user = User.objects.filter(email=username).first()
            if user:
                if make_password(password) == user.password:
                    return Response({'code': 200, 'msg': '登陆成功', 'jwt': encode_str})
                else:
                    return Response({'code': 400, 'msg': '密码不正确'})
            else:
                return Response({'code': 400, 'msg': '不存在该邮箱'})
        # else:
        #     return Response({'code': 400, 'msg': '验证码错误'})


from myapp.myser import *


# 用户详情
class UserInfoView(APIView):
    def get(self, request):
        username = request.GET.get('username')
        print(username)
        data = User.objects.filter(username=username).first()
        ser = UserSer(data)
        return Response(ser.data)


# 对比token
class ComparisonTokenView(APIView):
    def post(self, request):
        username = request.data.get('username')
        token = request.data.get('token')
        decode_jwt = jwt.decode(token, '123', algorithms='HS256')['data']
        token_username = decode_jwt['username']
        if username == token_username:
            return Response({'code': 200, 'msg': 'JWT_token值对比成功'})
        else:
            return Response({'code': 400, 'mag': '不是本人不允许修改密码'})


# 修改密码
class ChangePasswordView(APIView):
    def put(self, request):
        username = request.data.get('username')
        new_password = request.data.get('new_password')
        new_password = make_password(new_password)
        User.objects.filter(username=username).update(password=new_password)
        return Response({'code': 200, 'msg': '密码修改成功'})


# 添加图片
class AddImageView(APIView):
    def post(self, request):
        image = request.FILES.get('file')
        username = request.data.get('username')
        print(username, image)
        User.objects.filter(username=username).update(image=image)
        return Response({'code': 200, 'msg': '图片添加成功'})


# 优化获取的数据
def dictfetchall(cursor):
    desc = cursor.description
    return [
        dict(zip([col[0] for col in desc], row))
        for row in cursor.fetchall()
    ]


# 获取某个用户拥有的权限
class GetUserAccess(View):
    def get(self, request):
        # 获取参数
        token = request.GET.get('token')
        print(token)
        # 获取用户id
        decode_token = jwt.decode(token, '123', algorithms='HS256')['data']
        token_uid = decode_token['uid']
        print(token_uid)
        # 建立查询游标
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute(
            'SELECT a.username,c.permission_name,c.id FROM USER a LEFT JOIN  access b ON a.id = b.user_id LEFT JOIN permissions c on b.permission_id = c.id WHERE a.id= %s' % token_uid)
        # 获取结果集
        res = cursor.fetchall()
        # res = dictfetchall(cursor)
        return HttpResponse(json.dumps(res, ensure_ascii=False), content_type='application/json')


# 所有权限列表：
class PermissionListView(View):
    def get(self, request):
        # 建立查询游标
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute('SELECT * from PERMISSIONS')
        # 获取结果集
        res = cursor.fetchall()
        return HttpResponse(json.dumps(res, ensure_ascii=False), content_type='application/json')


# 给用户添加未拥有权限
class AddPermissionView(APIView):
    def post(self, request):
        token = request.data.get('token')
        pid = request.data.get('pid')
        decode_token = jwt.decode(token, '123', algorithms='HS256')['data']
        uid = decode_token['uid']
        print(uid, pid)
        access = Access.objects.filter(user=uid, permission=pid).first()
        if access:
            return Response({'code': 400, 'msg': '已拥有该权限 '})
        else:
            Access.objects.create(user_id=uid, permission_id=pid)
            return Response({'msg': '权限添加成功'})


permission_list = [{0b001: '个人中心'}, {0b001: '修改密码'}, {0b001: '上传头像'}]
user_list = [{1: 0b111}]


# 装饰器
def my_decorator(func):
    def wrapper(request, *args, **kwargs):
        print("装饰器被调用")
        return func(request, *args, **kwargs)

    return wrapper


# 上传头像
# @my_decorator
def upload_img(request):
    uid = request.GET.get('uid')
    pid = request.GET.get('pid')
    print(uid, pid)
    for user in user_list:
        print(user)
    # permission = permission_list[pid]
    # for permission_id in permission.items():
    #     permission_id = permission_id[0]
    #     print(permission_id)
    #     permission_id = int(permission_id[2:])
    #     b = bin(permission_id)
    # print(user, '==============', b)
    return HttpResponse('上传成功')


# 构造课程分类层级关系（树）
def get_tree(data):
    lists = []
    tree = {}
    for item in data:
        tree[item['id']] = item
    for i in data:
        if not i['pid']:
            lists.append(tree[i['id']])
        else:
            parent_id = i['pid']
            if 'children' not in tree[parent_id]:
                tree[parent_id]['children'] = []
            tree[parent_id]['children'].append(tree[i['id']])
    return lists


# 获取课程分类
def get_cate(request):
    # 建立游标查询
    cursor = connection.cursor()
    # 执行SQl
    cursor.execute('select * from cate')
    # 获取结果集
    # res = cursor.fetchall()
    res = dictfetchall(cursor)
    # 强转
    res = get_tree(res)
    return HttpResponse(json.dumps(res, indent=4, ensure_ascii=False), content_type='application/json')


# 添加课程
class AddCourse(APIView):
    def post(self, request):
        title = request.data.get('title', None)
        desc = request.data.get('desc', None)
        price = request.data.get('price', None)
        video = request.data.get('video', None)
        cid = request.data.get('cid', None)
        print(title, desc, price, video, cid)
        # 入库操作
        course = Course(title=title, desc=desc, price=price, video=video, cid=cid)
        # 保存
        course.save()
        return Response({'code': 200, 'msg': '课程提交成功'})


# 课程列表页
class CourseList(APIView):
    def post(self, request):
        # 当前页
        page = request.data.get('page')
        # 每一页展示条数
        size = request.data.get('size')
        # 开始位置
        print(page, size)
        data_start = (int(page) - 1) * int(size)
        # 结束位置
        data_end = int(page) * int(size)
        # 查询数据
        course_list = Course.objects.all()[data_start:data_end]
        # 总条数
        count = Course.objects.count()
        total = math.ceil(count / size)
        # 序列化操作
        course_list_ser = CourseSer(course_list, many=True)

        return Response({
            'total': total,
            'data': course_list_ser.data
        })


class CourseInfo(APIView):
    def get(self, request):
        cid = request.GET.get('cid')
        data = Course.objects.filter(id=cid).first()
        ser = CourseSer(data)
        return Response(ser.data)